#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

typedef unsigned long  LONG;
typedef unsigned short WORD;
typedef unsigned char  BYTE;


#define _free( x ) if ( x ){ free( x ); x = NULL; }

#define LGET( x, y ) *(LONG *)&x[ y ]
#define WGET( x, y ) *(WORD *)&x[ y ]

  BYTE *rom;

  LONG pList[0x1000],
      pCount;

  WORD pTable[ ] =
  {
    0xC9F0,
    0xCA92,
    0xCB30,
    0xCBD2,
//    0xCCBA,  // A special Block. Just pointers
    0xCD5C,
    0xCE01,
    0x0000
  };

  WORD addNum[ ] =
  {
    7 , 6,
    12, 6,
    27, 6,
    9 , 6,
//    0xCCBA,
    9, 6,
//    37, 6, // replaced by above
    9 , 6,
    0x0000
  };

  //------------------
  LONG posi,
       offset,
       count,
       loop;
  LONG value;
  LONG Lof;
  //---------------
  FILE *tf,
       *rf;

int main( /*int argc, char **argv*/ )
{
  rf = fopen( "c:/romhack/trans/Farland2/FS2j.smc", "rb" );
  tf = fopen( "c:/romhack/trans/Farland2/scripts.txt", "wt" );

  //
  if ( !tf || !rf )
  {
    printf( "Error: Could not open needed files." );
    fcloseall( );
    return -1;
  }

  //
  fseek( rf, 0, SEEK_END );
  Lof = ftell( rf );
  fseek( rf, 0, SEEK_SET );
  //

  rom = (BYTE *)malloc( Lof );
  if ( !rom )
  {
    printf( "Error: Could not allocate needed memory." );
    fcloseall( );
    _free( rom );
    return -1;
  }
  //
  fread( rom, 1, Lof, rf );
  fclose( rf );
  //


    //---------------------
    // Routine for batle intro text
    count = 0;
    while( count < 0x27 )
    { //
//      posi   = LGET( rom, 0xC9F0 + (count * 3) );
      posi   = WGET( rom, pTable[ loop ] + (count << 1) );
      posi  += 0xC10000;
      //
      offset =
      posi  &= 0x00FFFFFF;
      // Get the offset to the actual script data
      posi   = offset + addNum[ (loop << 1) ];
      posi  -= 0xC00000;
      value  = rom[ posi ] << 16;

      posi  += addNum[ (loop << 1) + 1 ];
      value += WGET( rom, posi );

      //
      for ( int c = 0; c < pCount; c++ )
      {
        if ( pList[ c ] == (value & 0xFFFFFF) ){
          fprintf( tf, "; .BLOCK %08X     // Duplicate\n", (value & 0xFFFFFF) );
          goto _Duplicate;
        }
      }
      //
      pList[ pCount++ ] = (value & 0xFFFFFF);
      fprintf( tf, ".BLOCK %08X\n", (value & 0xFFFFFF) );

      _Duplicate:
      count++;
    }
  }


/*
  loop = -1;
  while( pTable[ ++loop ] )
  {
    //
    fprintf( tf, "//-------------------------\n"
                 "// Data Table # %d\n"
                 "//-------------------------\n\n",
                 loop
           );
    //---------------------
    count = 0;
    while( count < 0x27 )
    { //
//      posi   = LGET( rom, 0xC9F0 + (count * 3) );
      posi   = LGET( rom, pTable[ loop ] + (count * 3) );
      //
      offset =
      posi  &= 0x00FFFFFF;
      // Get the offset to the actual script data
      posi   = offset + addNum[ (loop << 1) ];
      posi  -= 0xC00000;
      value  = rom[ posi ] << 16;

      posi  += addNum[ (loop << 1) + 1 ];
      value += WGET( rom, posi );

      //
      for ( int c = 0; c < pCount; c++ )
      {
        if ( pList[ c ] == (value & 0xFFFFFF) ){
          fprintf( tf, "; .BLOCK %08X     // Duplicate\n", (value & 0xFFFFFF) );
          goto _Duplicate;
        }
      }
      //
      pList[ pCount++ ] = (value & 0xFFFFFF);
      fprintf( tf, ".BLOCK %08X\n", (value & 0xFFFFFF) );

  /*
      fprintf( tf, "//-------------------------//\n"
                   "// Offset      : $%08X //\n"
                   "// Index       : $%02X       //\n"
                   "// Code        : $%08X //\n"
                   "// Routine Size: $%02X [%d]  //\n"
                   "//-------------------------//\n\n\n",
                   offset,
                   count,
                   (value & 0xFFFFFF),
                   (value & 0xFFFFFF) - offset,
                   (value & 0xFFFFFF) - offset
             );
  /
      //---------------------------
//      posi  += 7;
//      value  = WGET( rom, posi );
  //    fprintf( tf, "%04X\n", value );
      _Duplicate:
      count++;
    }
  }
*/


  _free( rom );
  fcloseall( );

  return 0;
}
